package com.imesne.office.excel.html;

import org.apache.poi.ss.usermodel.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by liyd on 17/7/17.
 */
public abstract class AbstractHtmlHelper implements HtmlHelper {

    protected static final Map<HorizontalAlignment, String> HALIGN = mapFor(
            HorizontalAlignment.LEFT, "left",
            HorizontalAlignment.CENTER, "center",
            HorizontalAlignment.RIGHT, "right",
            HorizontalAlignment.FILL, "left",
            HorizontalAlignment.JUSTIFY, "left",
            HorizontalAlignment.CENTER_SELECTION, "center");

    protected static final Map<VerticalAlignment, String> VALIGN = mapFor(
            VerticalAlignment.BOTTOM, "bottom",
            VerticalAlignment.CENTER, "middle",
            VerticalAlignment.TOP, "top");

    protected static final Map<BorderStyle, String> BORDER = mapFor(
            BorderStyle.DASH_DOT, "1pt dashed %s",
            BorderStyle.DASH_DOT_DOT, "1pt dashed %s",
            BorderStyle.DASHED, "1pt dashed %s",
            BorderStyle.DOTTED, "1pt dotted %s",
            BorderStyle.DOUBLE, "3pt double %s",
            BorderStyle.HAIR, "1px solid %s",
            BorderStyle.MEDIUM, "2pt solid %s",
            BorderStyle.MEDIUM_DASH_DOT, "2pt dashed %s",
            BorderStyle.MEDIUM_DASH_DOT_DOT, "2pt dashed %s",
            BorderStyle.MEDIUM_DASHED, "2pt dashed %s",
//            BorderStyle.NONE, "",
            BorderStyle.SLANTED_DASH_DOT, "2pt dashed %s",
            BorderStyle.THICK, "3pt solid %s",
            BorderStyle.THIN, "1pt solid %s");

//    private static final Map<BorderStyle, String> BORDER = mapFor(
//            BorderStyle.DASH_DOT, "dashed 1pt",
//            BorderStyle.DASH_DOT_DOT, "dashed 1pt",
//            BorderStyle.DASHED, "dashed 1pt",
//            BorderStyle.DOTTED, "dotted 1pt",
//            BorderStyle.DOUBLE, "double 3pt",
//            BorderStyle.HAIR, "solid 1px",
//            BorderStyle.MEDIUM, "solid 2pt",
//            BorderStyle.MEDIUM_DASH_DOT, "dashed 2pt",
//            BorderStyle.MEDIUM_DASH_DOT_DOT, "dashed 2pt",
//            BorderStyle.MEDIUM_DASHED, "dashed 2pt",
////            BorderStyle.NONE, "",
//            BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
//            BorderStyle.THICK, "solid 3pt",
//            BorderStyle.THIN, "solid 1pt");

    @SuppressWarnings({"unchecked"})
    private static <K, V> Map<K, V> mapFor(Object... mapping) {
        Map<K, V> map = new HashMap<K, V>();
        for (int i = 0; i < mapping.length; i += 2) {
            map.put((K) mapping[i], (V) mapping[i + 1]);
        }
        return map;
    }

    private Map<CellStyle, String> seen = new HashMap<>();

    public List<String> cellStyleToHtmlStyle(Workbook workbook, CellStyle style) {
        List<String> cellStyles = new ArrayList<>();
        addStyle("text-align", style.getAlignmentEnum(), HALIGN, cellStyles);
        addStyle("vertical-align", style.getVerticalAlignmentEnum(), VALIGN, cellStyles);
        addFontStyle(workbook, style, cellStyles);
//        addBorderStyles(style, cellStyles);
        List<String> styles = this.getStyles(workbook, style);
        cellStyles.addAll(styles);
        return cellStyles;
    }

    public String cellStyleName(Workbook workbook, CellStyle style) {
        if (style == null) {
            style = workbook.getCellStyleAt((short) 0);
        }
        //某些情况下 CellStyle.equals()相同，style.getIndex()不同
        String name = seen.get(style);
        if (name != null) {
            return name;
        }
        seen.put(style, name);
        return String.format("style_%02x", style.getIndex());
    }

    public boolean isCellStyleNameExists(CellStyle style) {
        return seen.containsKey(style);
    }

//    protected void addBorderStyles(CellStyle style, List<String> cellStyles) {
//        addStyle("border-left", style.getBorderLeftEnum(), BORDER, cellStyles);
//        addStyle("border-right", style.getBorderRightEnum(), BORDER, cellStyles);
//        addStyle("border-top", style.getBorderTopEnum(), BORDER, cellStyles);
//        addStyle("border-bottom", style.getBorderBottomEnum(), BORDER, cellStyles);
//    }

    protected void addFontStyle(Workbook workbook, CellStyle style, List<String> cellStyles) {
        Font font = workbook.getFontAt(style.getFontIndex());
        if (font.getBold()) {
            cellStyles.add(String.format("font-weight: bold;"));
        }
        if (font.getItalic()) {
            cellStyles.add(String.format("font-style: italic;"));
        }
        int fontheight = font.getFontHeightInPoints();
        if (fontheight == 9) {
            //fix for stupid ol Windows
            fontheight = 10;
        }
        cellStyles.add(String.format("font-size: %dpt;", fontheight));
        // Font color is handled with the other colors
    }

    protected <K> void addStyle(String attr, K key, Map<K, String> mapping, List<String> cellStyles) {
        String value = mapping.get(key);
        if (value != null) {
            cellStyles.add(String.format("%s: %s;", attr, value));
        }
    }

    /**
     * Outputs the appropriate CSS style for the given cell style.
     *
     * @param workbook the workbook
     * @param style    The cell style.
     * @return the map
     */
    public abstract List<String> getStyles(Workbook workbook, CellStyle style);
}
